package com.greateamd.timetableasy.server.dao;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;

import net.sf.gilead.pojo.gwt.LightEntity;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Projections;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;

public abstract class AbsBaseDao<T extends LightEntity, ID extends Serializable> implements IBaseDao<T, ID> {
	
	private final T type;
	
	public AbsBaseDao(final T type) {
		this.type = type;
	}
	   
	public HibernateTemplate hibernateTemplate;

	public void setHibernateTemplate(HibernateTemplate hibernateTemplate){
        this.hibernateTemplate = hibernateTemplate;
    }

	public HibernateTemplate getHibernateTemplate(){
        return hibernateTemplate;
    }
	
	@Override
	public void delete(final T obj) {     
		HibernateCallback callback = new HibernateCallback() {
	         public Object doInHibernate(Session session) throws HibernateException,SQLException {
	             session.delete(obj);
	             return null;
	         }
	     };
	     getHibernateTemplate().execute(callback);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> getAll() {
		HibernateCallback callback = new HibernateCallback() {

			public Object doInHibernate(Session session) throws HibernateException,SQLException {
				
				String requeteFrom = type.getClass().getName();
        		List<T> result = session.createQuery("from "+requeteFrom).list();
                return result;
            }
        };
        return (List<T>) getHibernateTemplate().execute(callback);
	}

	@SuppressWarnings("unchecked")
	@Override
	public T getById(final ID id) {
		HibernateCallback callback = new HibernateCallback() {

			public Object doInHibernate(Session session) throws HibernateException,SQLException {
				Class typeClass = type.getClass();
				T ret = (T) session.get(typeClass, id);
                return ret ;
            }
        };        
        return (T) getHibernateTemplate().execute(callback);
	}

	@Override
	public void save(final T obj) throws HibernateException,SQLException {
		HibernateCallback callback = new HibernateCallback() {
	         public Object doInHibernate(Session session) throws HibernateException,SQLException {
	             session.save(obj);
	             return null;
	         }
	     };
	     getHibernateTemplate().execute(callback);
	}

	@Override
	public void save(final List<T> obj) throws HibernateException,SQLException{
		HibernateCallback callback = new HibernateCallback() {
	         public Object doInHibernate(Session session) throws HibernateException,SQLException {
	        	 for(T toSave : obj){
	        		 session.save(toSave);
	        	 }
	             return null;
	         }
	     };
	     getHibernateTemplate().execute(callback);
	}
	
	@Override
	public void update(final T obj) {
		HibernateCallback callback = new HibernateCallback() {
	         public Object doInHibernate(Session session) throws HibernateException,SQLException {
	             session.update(obj);
	             return null;
	         }
	     };
	     getHibernateTemplate().execute(callback);
	}
	
	@Override
	public void saveOrUpdate(final T obj) {
		HibernateCallback callback = new HibernateCallback() {
	         public Object doInHibernate(Session session) throws HibernateException,SQLException {
	             session.saveOrUpdate(obj);
	             return null;
	         }
	     };
	     getHibernateTemplate().execute(callback);
	}
	
	@Override
	public Integer getRowCount() {
		HibernateCallback callback = new HibernateCallback() {
	         public Object doInHibernate(Session session) throws HibernateException,SQLException {
	            Criteria criteria = session.createCriteria(type.getClass());
	     		criteria.setProjection(Projections.rowCount());
	    		Integer result = (Integer) criteria.uniqueResult();
	    		System.out.println("Nombre d'enregistrements : " + result);
	    		return result;
	         }
	     };
	     return (Integer) getHibernateTemplate().execute(callback);
	}
}
